package mysql

import (
	"douyin/models"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

// Follow 关注
func Follow(toUserId, userId int64) (err error) {
	//1.用户1是否关注了用户2
	isDel, err := WhetherUserFollow(toUserId, userId)
	//2. 查不到,直接插入这条数据
	if err == ErrorQueryZeroRecord {
		err = nil
		f := &models.Relation{
			BeFollow: toUserId,
			Follow:   userId,
			IsDel:    false,
		}
		tx := db.Debug().Model(&models.Relation{}).Create(f)
		if tx.Error != nil {
			err = tx.Error
			return
		}
		return
	}
	if err != nil {
		zap.L().Error("mysql.Follow failed", zap.Error(err))
		return
	}
	//3.1 isDel:false 不做操作
	if !isDel {
		return
	}
	//3.2.isDel为true, 更新isDel=false
	if isDel {
		tx := db.Debug().Model(&models.Relation{}).Where("be_follow = ? AND follow = ?", toUserId, userId).Update("is_del", false)
		if tx.Error != nil {
			err = tx.Error
			return
		}
		return
	}
	return
}

// UnFollow 取消关注
func UnFollow(toUserId, userId int64) (err error) {
	//1.用户1是否关注了用户2
	isDel, err := WhetherUserFollow(toUserId, userId)
	//2.查不到数据，直接返回，减少sql操作；也可以插入一条记录，其中记录isDel改为true
	if err == ErrorQueryZeroRecord {
		err = nil
		return
	}
	if err != nil {
		zap.L().Error("mysql.UnFollow failed", zap.Error(err))
		return
	}
	//3.1 isDel:true 不做操作
	if isDel {
		return
	}
	//3.2.isDel为false, 更新isDel=true
	if !isDel {
		tx := db.Debug().Model(&models.Relation{}).Where("be_follow = ? AND follow = ?", toUserId, userId).Update("is_del", true)
		if tx.Error != nil {
			err = tx.Error
			return
		}
		return
	}
	return
}

// WhetherFollow A用户是否关注B用户
func WhetherFollow(myId, otherId int64) (isFollow bool) {
	isDel, err := WhetherUserFollow(otherId, myId)
	//查不到数据
	if err == ErrorQueryZeroRecord {
		return false
	}
	if err != nil {
		return false //查找关系，发生错误，默认未关注
	}
	//之前关注过，现在取消关注了
	if isDel {
		return false
	}
	//现在关注着
	if !isDel {
		return true
	}
	return false //默认未关注
}

// WhetherUserFollow A用户是否关注B用户
func WhetherUserFollow(toUserId, userId int64) (isDel bool, err error) {
	tx := db.Debug().Model(&models.Relation{}).Select("is_del").Where("be_follow = ? AND follow = ?", toUserId, userId).First(&isDel)
	//1.查不到数据
	if tx.Error == gorm.ErrRecordNotFound {
		err = ErrorQueryZeroRecord
		return
	}
	//2.查询发生其他错误，默认未关注
	if tx.Error != nil {
		isDel = true
		err = tx.Error
		return
	}
	//3.没进入上面的判断，说明查得到,isDel会被赋值为true或false
	return
}

// SelectFollowList 关注列表
func SelectFollowList(userId int64) (followIds []int64, err error) {
	tx := db.Debug().Model(&models.Relation{}).Select("be_follow").Where("follow = ? AND is_del = ?", userId, false).Find(&followIds)
	//找不到记录，报错
	if len(followIds) == 0 {
		return nil, ErrorQueryZeroRecord
	}
	//未知错误
	if tx.Error != nil {
		return nil, tx.Error
	}
	return
}

// SelectFollowerList 粉丝列表
func SelectFollowerList(userId int64) (followerIds []int64, err error) {
	tx := db.Debug().Model(&models.Relation{}).Select("follow").Where("be_follow = ? AND is_del = ?", userId, false).Find(&followerIds)
	//找不到记录，报错
	if len(followerIds) == 0 {
		return nil, ErrorQueryZeroRecord
	}
	//未知错误
	if tx.Error != nil {
		return nil, tx.Error
	}
	return
}

// CombiFollow 组合用户的关注列表
func CombiFollow(userIds []int64, myself int64) (userList []models.User, err error) {
	//构建userList
	for _, v := range userIds {
		//1.查用户
		u, _ := SelectUserByUserId(v)
		//2.查我是否关注此用户
		u.IsFollow = WhetherFollow(myself, u.Id) //自己id,对方id
		userList = append(userList, u)
	}
	return
}

// CombiFollower 组合用户的粉丝列表
func CombiFollower(userIds []int64, myself int64) (userList []models.User, err error) {
	//构建userList
	for _, v := range userIds {
		//1.查用户
		u, _ := SelectUserByUserId(v)
		//2.查我是否关注用户
		u.IsFollow = WhetherFollow(myself, u.Id) //自己id,对方id
		userList = append(userList, u)
	}
	return
}

// RelationCount 维护follow和follower count
func RelationCount(toUserId, userId int64, isAdd bool) (err error) {
	var str string
	var condition1 string
	var condition2 string
	if isAdd {
		//toUserId的粉丝+1，userId的关注+1
		str = "+"
		condition1 = ""
		condition2 = ""
	} else {
		//toUserId的粉丝-1，userId的关注-1
		str = "-"
		condition1 = " AND follow_count>0"
		condition2 = " AND follower_count>0"
	}
	//toUserId
	tx1 := db.Debug().Model(&models.User{}).Where("user_id = ?"+condition2, toUserId).Update("follower_count", gorm.Expr("follower_count"+str+" ?", 1))
	//userId
	tx2 := db.Debug().Model(&models.User{}).Where("user_id = ?"+condition1, userId).Update("follow_count", gorm.Expr("follow_count"+str+" ?", 1))

	if tx1.RowsAffected == 0 || tx2.RowsAffected == 0 {
		err = ErrorUpdateFailed
		return
	}
	if tx1.Error != nil {
		err = tx1.Error
		return
	}
	if tx2.Error != nil {
		err = tx2.Error
		return
	}
	return
}
